﻿// Copyright (c) 2011 Blue Onion Software, All rights reserved
using System;
using System.Configuration.Provider;
using System.IO;
using System.Web.Configuration;

namespace BlueOnionSoftware.Bloget.Providers
{
    internal abstract class BlogProvider : ProviderBase
    {
        private static readonly object padLock = new object();
        private static BlogProvider provider;
        private static ProviderCollection providers;

        internal abstract Blog Load(string context);
        internal abstract void Save(Blog blog, string context);
        internal abstract Content LoadContent(Guid id, string context);
        internal abstract void SaveContent(Guid id, Content content, string context);
        internal abstract void Backup(Blog blog, Stream stream);

        internal static BlogProvider DefaultProvider
        {
            get { return provider ?? LoadDefaultProvider(); }
        }

        internal static ProviderCollection Providers
        {
            get { return providers ?? LoadProviders(); }
        }

        private static BlogProvider LoadDefaultProvider()
        {
            LoadProviders();
            return provider;
        }

        private static ProviderCollection LoadProviders()
        {
            lock (padLock) // load only once
            {
                if (provider == null)
                {
                    providers = new ProviderCollection();
                    var section = (BlogProviderSection) WebConfigurationManager.GetSection("Bloget/blogProvider");

                    if (section == null)
                    {
                        provider = new XmlBlogProvider();
                        provider.Initialize("XmlBlogProvider", null);
                        providers.Add(provider);
                    }

                    else
                    {
                        ProvidersHelper.InstantiateProviders(section.Providers, providers, typeof (BlogProvider));
                        provider = (BlogProvider) providers[section.DefaultProvider];
                    }

                    if (provider == null)
                    {
                        throw new ProviderException("Unable to load default BlogProvider");
                    }
                }
            }

            return providers;
        }

        internal static void LoadProviderForUnitTests()
        {
            lock (padLock) // load only once
            {
                provider = new XmlBlogProvider();
                provider.Initialize("XmlBlogProvider", null);
                providers = new ProviderCollection();
                providers.Add(provider);
            }
        }
    }
}